package com.hd.trans.network;

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;


import com.hd.trans.network.annotation.FileName;
import com.hd.trans.network.annotation.Get;
import com.hd.trans.network.annotation.KeyExtension;
import com.hd.trans.network.annotation.MultSet;
import com.hd.trans.network.annotation.MultSetKeyExtension;
import com.hd.trans.network.annotation.MultSetParam;
import com.hd.trans.network.annotation.Param;
import com.hd.trans.network.annotation.Set;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;

import androidx.annotation.Nullable;

/**
 * Author:  yang
 * Date:    2020/01/19 9:15
 * Desc:    Preference处理代理类(参考了Retrofit写法)
 */
public class PreferenceProxy {
    @SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
    public <T> T create(final Context context, final Class<T> service) {
        if (!service.isInterface()) {
            throw new IllegalArgumentException("API declarations must be interfaces.");
        }
        if (service.getInterfaces().length > 0) {
            throw new IllegalArgumentException("API interfaces must not extend other interfaces.");
        }
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[]{service},
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, @Nullable Object[] args)
                            throws Throwable {
                        // If the method is a method from Object then defer to normal invocation.
                        if (method.getDeclaringClass() == Object.class) {
                            return method.invoke(this, args);
                        }
                        String fileName = "preference." + service.getSimpleName();
                        String temp = "";
                        if (service.isAnnotationPresent(FileName.class)) {
                            FileName annotation = service.getAnnotation(FileName.class);
                            temp = annotation.value();
                        }
                        if (!TextUtils.isEmpty(temp)) {
                            fileName = temp;
                        }

                        Object param = null;//以第一个@Param标记作为参数(找不到则第一个没用注解约束的作为参数值)
                        String keyExtension = "";
                        Type[] parameterTypes = method.getGenericParameterTypes();
                        int otherParamIndex = -1;

                        Map<String, Object> multParams = new HashMap<>();//多条设置
                        Map<String, String> multKeyExtension = new HashMap<>();//多条设置


                        Annotation[][] parameterAnnotationsArray = method.getParameterAnnotations();
                        for (int i = 0; i < parameterAnnotationsArray.length; i++) {
                            Annotation[] parameterAnnotations = parameterAnnotationsArray[i];
                            boolean hasAnnotation = false;
                            for (Annotation annotation : parameterAnnotations) {
                                hasAnnotation = true;
                                if (annotation.annotationType().equals(KeyExtension.class)) {
                                    keyExtension += args[i];
                                } else if (annotation.annotationType().equals(Param.class)) {
                                    if (param == null)
                                        param = args[i];
                                } else if (annotation.annotationType().equals(MultSetKeyExtension.class)) {
                                    multKeyExtension.put( ((MultSetKeyExtension)annotation).value() , String.valueOf(args[i]));
                                } else if (annotation.annotationType().equals(MultSetParam.class)) {
                                    multParams.put( ((MultSetParam)annotation).value() ,args[i]);
                                }
                            }if ( !hasAnnotation && otherParamIndex == -1) {
                                otherParamIndex = i;
                            }
                        }
                        if (param == null && args != null && args.length > 0) {
                            if (otherParamIndex == -1)
                                otherParamIndex = 0;
                            param = args[otherParamIndex];
                        }


                        SharedPreferences sp = context.getApplicationContext().getSharedPreferences(fileName, Context.MODE_PRIVATE);
                        if (method.isAnnotationPresent(Set.class)) {
                            SharedPreferences.Editor editor = sp.edit();

                            Set set = method.getAnnotation(Set.class);
//                            Type[] paramTypes = method.getGenericParameterTypes();

                            String key = set.value() + keyExtension;
                            /** 只处理第一个合法参数 */
                            if (param != null) {
//                                Log.i("T","=========== key : "+key);
//                                Log.i("T","=========== param : "+param);
//                                Type paramType = paramTypes[0];
                                if (param instanceof Boolean) {
                                    editor.putBoolean(key, (Boolean) param);
                                } else if (param instanceof String) {
                                    editor.putString(key, (String) param);
                                } else if (param instanceof Integer) {
                                    editor.putInt(key, (Integer) param);
                                } else if (param instanceof Float) {
                                    editor.putFloat(key, (Float) param);
                                } else if (param instanceof Long) {
                                    editor.putLong(key, (Long) param);
                                }
                                //TODO
                                editor.commit();
                            }
//                            Annotation[][] parameterAnnotations = method.getParameterAnnotations();
//                            for (Annotation[] annotations : parameterAnnotations) {
//                                for (Annotation annotation : annotations) {
//                                    //获取注解名
//                                    String name = annotation.annotationType().getSimpleName();
//                                }
//                            }

                        } else if (method.isAnnotationPresent(Get.class)) {
                            Get get = method.getAnnotation(Get.class);

                            String key = get.value() + keyExtension;
                            Type returnType = method.getGenericReturnType();
                            if (returnType == boolean.class) {
                                return sp.getBoolean(key, get.defaultBoolean());
                            } else if (returnType == String.class) {
                                return sp.getString(key, get.defaultString());
                            } else if (returnType == int.class) {
                                return sp.getInt(key, get.defaultInt());
                            } else if (returnType == float.class) {
                                return sp.getFloat(key, get.defaultFloat());
                            } else if (returnType == long.class) {
                                return sp.getLong(key, get.defaultLong());
                            }
                        }else if( method.isAnnotationPresent(MultSet.class)){
                            SharedPreferences.Editor editor = sp.edit();
                            MultSet multSet = method.getAnnotation(MultSet.class);
                            String[] keys = multSet.value();
                            for ( String key: keys ){
                                String realKey = key;
                                if (multKeyExtension.containsKey(key)){
                                    realKey  += multKeyExtension.get(key);
                                }
                                if (multParams.containsKey(key)){
                                    Object realParam = multParams.get(key);
                                    if (realParam instanceof Boolean) {
                                        editor.putBoolean(realKey, (Boolean) realParam);
                                    } else if (realParam instanceof String) {
                                        editor.putString(realKey, (String) realParam);
                                    } else if (realParam instanceof Integer) {
                                        editor.putInt(realKey, (Integer) realParam);
                                    } else if (realParam instanceof Float) {
                                        editor.putFloat(realKey, (Float) realParam);
                                    } else if (realParam instanceof Long) {
                                        editor.putLong(realKey, (Long) realParam);
                                    }
                                }
                            }
                            editor.commit();
                        }
                        //TODO
//                        return method.invoke(this, args);
                        return null;
                    }
                });
    }



}
